# -*- coding: utf-8 -*-
# this file is released under public domain and you can use without limitations

#########################################################################
## This is a samples controller
## - index is the default action of any application
## - upload is for uploading data files to the db
## - list is to list the data uploaded in the system so far by the user
#########################################################################

def index():
    """
    example action using the internationalization operator T and flash
    rendered by views/default/index.html or views/generic.html
    """
    response.title = "Open Spatial Data"
    response.flash = "Available data"
    return dict(message=T('Hello World'))


"""
This function returns a listing of the files that have been uploaded
Open to both logged in and anonymous users
"""    
def list():
    response.title = 'Spatial Data'
    response.subtitle = 'View uploaded spatial data'
    import os.path
        
    listQuery = (db.auth_user.id==db.files.owner_id)
    listForm = SQLFORM.grid(listQuery, 
                            fields = [db.files.id, db.auth_user.first_name, db.files.data_file_name, db.files.data_file_extension, db.files.data_file_path, db.files.data_file_description, db.files.upload_datetime],
                            field_id = db.files.id,
                            orderby = db.files.upload_datetime,
                            left = db.auth_user.on(db.auth_user.id==db.files.owner_id), #Jinson - this one currently has minor bug if the join id isn't specified in the query object. Minor inefficiency now in resulting sql as id join is specified in both left join ON and the where clause
                            headers = {'auth_user.first_name':'Owner','files.data_file_name':'File name', 'files.data_file_extension':'Type','files.upload_datetime':'Uploaded on'},
                            maxtextlengths = {'files.data_file_description':64,'files.data_file_path':64},
                            deletable = False, editable = False, create = False, details = False)	
        
    return dict(fileListingForm = listForm)


def upload():
    response.title = 'Spatial Data'
    response.subtitle = 'View uploaded spatial data and upload your own!'
    if (session and session.auth):
    
        if("download" in request.args):
            download()
        else:
    
            import os.path
            form = SQLFORM(db.files, deletable=True, fields = ['data_file_description', 'data_file'])
            
            listQuery = (db.auth_user.id==db.files.owner_id) & (db.files.owner_id == session.auth.user.id)
            listForm = SQLFORM.grid(listQuery, upload='download',
                                    fields = [db.files.id, db.auth_user.first_name, db.files.data_file_name, db.files.data_file_extension, db.files.data_file_description, db.files.data_file, db.files.upload_datetime],
                                    field_id = db.files.id,
                                    orderby = db.files.upload_datetime,
                                    left = db.auth_user.on(db.auth_user.id==db.files.owner_id), #Jinson - this one currently has minor bug if the join id isn't specified in the query object. Minor inefficiency now in resulting sql as id join is specified in both left join ON and the where clause
                                    headers = {'auth_user.first_name':'Owner','files.data_file_name':'File name', 'files.data_file_extension':'Type','files.data_file':'File','files.upload_datetime':'Uploaded on'},
                                    maxtextlengths = {'files.data_file_description':64,'files.data_file_path':64})
       
            if (form.process(onvalidation = processUpload).accepted):            
                session.flash = T("File " + session.originalFileName + " uploaded")
                del session.originalFileName
                redirect(URL('upload'))
            
            return dict(fileUploadForm = form, fileListingForm = listForm)


    
    else:
        msgContent = T('Uploads only allowed for registered users. Please login or register.')
        session.flash = msgContent;
        redirect(URL(c='default', f='user', args=['login'], vars={'_next':'/' + request.application + '/data/upload'}))
        return dict(message = msgContent)
    
    
def processUpload(form):
    import datetime
    import os.path
    
    path = os.path.join('uploads', 'files', str(session.auth.user.id))    
    processFileName(form, path)
    
    session.originalFileName = form.vars.data_file.filename
    form.vars.owner_id = session.auth.user.id if (session.auth.user) else 1  # default value of user id 1
    form.vars.upload_datetime = datetime.datetime.now()  # set the upload datetime
    form.vars.data_file_name = os.path.splitext(session.originalFileName)[0][0:].strip()
    form.vars.data_file_extension = os.path.splitext(str(form.vars.data_file.filename))[1][1:].strip()
    form.vars.data_file_path = path
    
    
    
# function that checks filename existence on disk and dynamically changes filename if already exists
def processFileName(form, path):
    import os
    
    logger.debug('Within processFileName function')
    
    fullFileName = str(form.vars.data_file.filename)
    fileName = os.path.splitext(fullFileName)[0][0:].strip()
    extension = os.path.splitext(str(fullFileName))[1][1:].strip()
    
    # check for existing file in the user's upload dir. If exists, rename the file according to algorithm. 
    # Same file name but different file types already catered to by checking for exists using fullFileName
    if (os.path.isfile(os.path.join(request.folder, path, fullFileName))):
        # loop through list to search for filenames with our extension format. 
        # Record each num found in another list. 
        # After dir filename list is looped and if list count is > 0, sort the num list in desc order, pick first and +1.
        # Else if list is empty, append num extension 1 to it if is not already extended.

        logger.debug('File ' + fullFileName + ' already exists. Now generating new filename...')
        import re

        fileList = os.listdir(os.path.join(request.folder, path))
        extTrackList = []      
        

        # first check whether current filename is already extended
        isExtended = re.match(r"(?P<filePref>.+)-_cp(\d+)$", fileName)
        filePrefix = isExtended.group('filePref') if (isExtended) else fileName
        logger.debug('filePrefix is "' + filePrefix + '"')
        
        numMarkerRegXp = re.compile(re.escape(filePrefix) + "-_cp(?P<curNum>\d+)$")
        
        for dirFile in fileList:
            logger.debug('Found file: "' + dirFile + '"')
            result = numMarkerRegXp.match(os.path.splitext(dirFile)[0][0:].strip())        
            if (result != None):
                #logger.debug('File is numExtended, ')
                # add the number into the extTrackList
                extTrackList.append(result.group('curNum'))

                
        logger.debug('Found ' + str(len(extTrackList)) + ' files with our numbering extension')
        # generate the new extension number
        newNum = int(sorted(extTrackList)[len(extTrackList) - 1]) + 1 if (len(extTrackList) > 0) else 1
        newFullFileName = filePrefix + '-_cp' + str(newNum) + '.' + extension
        
        form.vars.data_file.filename = newFullFileName    

        logger.debug(newFullFileName)
        
        
    
def download():
    import gluon.contenttype as c

    if not request.args:
        raise HTTP(404)
    name = request.args[-1]
    field = db["files"]["data_file"]
    try:
        (filename, file) = field.retrieve(name)
    except IOError:
        raise HTTP(404)
    response.headers["Content-Type"] = c.contenttype(name)
    response.headers["Content-Disposition"] = "attachment; filename=%s" % name
    stream = response.stream(file, chunk_size=64*1024, request=request)
    raise HTTP(200, stream, **response.headers)    